package com.zerui.manager.icc.conf;

import com.alibaba.fastjson.JSONObject;
import com.dahuatech.icc.event.enums.CategoryEnums;
import com.dahuatech.icc.multiinone.event.EventSubcribeSDK;
import com.dahuatech.icc.multiinone.event.domain.*;
import com.dahuatech.icc.multiinone.event.vo.CancelSubcribeRequest;
import com.dahuatech.icc.multiinone.event.vo.EventSubcribeRequest;
import com.zerui.manager.icc.properties.ICCProperties;
import com.zerui.manager.icc.service.AccessControlInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.ResourceLoader;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ICC文件字典配置  字典配置来原因文件
 */
@Slf4j
@Configuration
@Order(value = 15)
public class ICCDictFileConf implements CommandLineRunner {

    @Resource
    private ICCProperties iccProperties;

    @Resource
    private ICCOAuthConfigHolder iccOauthConfigHolder;
    @Resource
    private AccessControlInfoService accessControlInfoService;

    @Resource
    private ResourceLoader resourceLoader;

    private String alarmTypeFile = "classpath:icc_alarm_type.txt";
    private String deviceCategoryFile = "classpath:icc_device_category.txt";
    private String deviceManufacturerFile = "classpath:icc_device_manufacturer.txt";

    // 报警类型
    private final Map<String, String> alarmTypesMap = new ConcurrentHashMap<>();
    // 设备分类 - 大分类
    private final Map<String, String> categoriesMap = new ConcurrentHashMap<>();
    // 设备分类 - 小分类
    private final Map<String, Map<String, String>> category2TypesMap = new ConcurrentHashMap<>();
    // 设备厂商
    private final Map<String, String> manufacturersMap = new ConcurrentHashMap<>();

    @Override
    public void run(String... args) throws Exception {
        log.info("1、加载ICC字典......");
        // 设备大类、小类
        List<String> lines = this.readLines(deviceCategoryFile);
        Map<String, String> currCategoryTypesMap = null; // 当前分类下子类型
        for (String line : lines) {
            if (!line.startsWith(" ")) {
                String[] line_arr = line.split("\t");
                if (line_arr.length != 2) continue;
                currCategoryTypesMap = new HashMap<>();
                category2TypesMap.put(line_arr[0], currCategoryTypesMap);
                categoriesMap.put(line_arr[0], line_arr[1]);
            } else {
                line = line.trim(); // 去掉开头的两个\t
                String[] line_arr = line.split("\t");
                if (line_arr.length < 2)
                    System.out.println(line);
                currCategoryTypesMap.put(line_arr[0], line_arr[1]);
            }
        }
        // 厂商字典
        List<String> lines2 = this.readLines(deviceManufacturerFile);
        for (String line : lines2) {
            String[] line_arr = line.split("\t");
            if (line_arr.length != 2) continue;
            manufacturersMap.put(line_arr[0], line_arr[1]);
        }
        // 报警类型
        List<String> lines3 = this.readLines((alarmTypeFile));
        for (String line : lines3) {
            String[] line_arr = line.split("\t");
            if (line_arr.length < 2) continue;
            alarmTypesMap.put(line_arr[0], line_arr[1]);
        }
        log.info("2、订阅ICC报警事件......");
        this.subscribeAlarmEvents();
    }

    // 读取文件每行记录
    private List<String> readLines(String fileP) throws IOException {
        List<String> lines = new ArrayList<>();
        org.springframework.core.io.Resource resource = resourceLoader.getResource(fileP);
        try (InputStream resourceAsStream = resource.getInputStream();
             InputStreamReader isr = new InputStreamReader(resourceAsStream);
             BufferedReader br = new BufferedReader(isr)) {
            String data = null;
            while ((data = br.readLine()) != null) {
                lines.add(data);
            }
        } catch (Exception ex) {
            log.error("读取文件失败", ex);
        }
        return lines;
    }

    /**
     * 获取大分类代码文本
     *
     * @param category 大分类
     * @return
     */
    public String getCategoryName(final String category) {
        if (StringUtils.isEmpty(category)) return null;
        return categoriesMap.get(category);
    }

    /**
     * 获取小分类代码文本
     *
     * @param category 大分类
     * @param type     小分类
     * @return
     */
    public String getDeviceTypeName(final String category, final String type) {
        if (StringUtils.isEmpty(category)) return null;
        if (category2TypesMap.containsKey(category)) {
            if (StringUtils.isEmpty(type)) return null;
            Map<String, String> typesMap = category2TypesMap.get(category);
            return typesMap.get(type);
        }
        return null;
    }

    /**
     * 获取厂商名称
     *
     * @param manufacturer
     * @return
     */
    public String getManufacturerName(final String manufacturer) {
        if (StringUtils.isEmpty(manufacturer)) return null;
        return manufacturersMap.get(manufacturer);
    }

    /**
     * 获取报警类型名称
     *
     * @param alarmType 报警类型
     * @return
     */
    public String getAlarmTypeName(final String alarmType) {
        if (StringUtils.isEmpty(alarmType)) return null;
        return alarmTypesMap.get(alarmType);
    }

    // 订阅报警记录
    private void subscribeAlarmEvents() {
        //final String magic = subscribeIP + "_" + subscribePort;
        //final String callback = "http://" + subscribeIP + ":" + subscribePort + subscribeCallback;

        /*SubscribeEventVO eventVO = SubscribeEventVO.builder()
                .category("alarm")
                .authority(typeSet.toArray(new String[typeSet.size()]))
                .build();
        SubscribeVO subscribeVO = SubscribeVO.builder()
                .magic(magic)
                .monitor(callback, Collections.singletonList(eventVO))
                .build();

        System.out.println(JSONObject.toJSONString(subscribeVo));
        try {
            JSONObject joSubscribes = accessControlInfoService.listSubscribe();
            if (joSubscribes.containsKey(magic)) {
                log.info("报警事件[{}],已订阅.", magic);
                accessControlInfoService.cancelSubscribe(magic);
            }
            accessControlInfoService.subscribeAlarmEvents(subscribeVO);
        } catch (ClientException e) {
            log.error("订阅ICC报警事件出错", e);
        }*/


        try {
            // 启动执行订阅流程
            EventSubcribeSDK pushPersonCardToThirdPartySDK = new EventSubcribeSDK();
            EventSubcribeRequest request = new EventSubcribeRequest();
            request.setOauthConfigBaseInfo(iccOauthConfigHolder.getOauthConfigClientInfo());
            // 订阅参数
            SubscribeParamVo subscribeParamVo = new SubscribeParamVo();
            // 系统
            SubsystemVo subsystemVo = new SubsystemVo();
            subsystemVo.setName(iccProperties.getCallbackClientId());
            subsystemVo.setMagic(iccProperties.getCallbackClientId());
            subscribeParamVo.setSubsystem(subsystemVo);
            // 监视组
            List<MonitorVo> monitorVos = new ArrayList<>();
            MonitorVo monitorVo = new MonitorVo();
            monitorVo.setMonitor(iccProperties.getCallbackEndpoint());
            // 报警事件
            List<EventVo> eventVos = new ArrayList<>();
            EventVo alarmEventVo = new EventVo();
            alarmEventVo.setCategory(CategoryEnums.alarm.code);
            List<AuthorityVo> alarmAuthorities = new ArrayList<>();
            AuthorityVo alarmAuthorityVo = new AuthorityVo();
            alarmAuthorityVo.setTypes(new ArrayList<>(alarmTypesMap.keySet())); // 类型
            alarmAuthorityVo.setNodeCodes(null);//null代表所有 nodeCodes与orgs是取并集
            alarmAuthorityVo.setOrgs(null);//null 代表所有 nodeCodes与orgs是取并集
            alarmAuthorities.add(alarmAuthorityVo);
            alarmEventVo.setAuthorities(alarmAuthorities);//null 代表所有，空数组代表不订阅
            eventVos.add(alarmEventVo);
            monitorVo.setEvents(eventVos);
            monitorVos.add(monitorVo);
            subscribeParamVo.setMonitors(monitorVos);
            SubscribeVo subscribeVo = new SubscribeVo();
            subscribeVo.setParam(subscribeParamVo);
            request.setSubscribeVo(subscribeVo);

            JSONObject joSubscribes = accessControlInfoService.listSubscribe();
            if (joSubscribes.containsKey(iccProperties.getCallbackClientId())) {
                log.info("报警事件[{}],已订阅.", iccProperties.getCallbackClientId());
                CancelSubcribeRequest cancelSubcribeRequest = new CancelSubcribeRequest();
                cancelSubcribeRequest.setOauthConfigBaseInfo(iccOauthConfigHolder.getOauthConfigClientInfo());
                cancelSubcribeRequest.setName(iccProperties.getCallbackClientId());
                pushPersonCardToThirdPartySDK.cancelSubcribe(cancelSubcribeRequest);
            }
            pushPersonCardToThirdPartySDK.eventSubscribe(request);
        } catch (Exception e) {
            log.error("订阅ICC报警事件出错", e);
        }
    }
}
